import calendar
import datetime
import sys

sys.setrecursionlimit(1000000)

from django.db.models import Sum
from rest_framework import serializers

from databases.models import *


class AppUserSerializer(serializers.ModelSerializer):
    """
    基础用户表
    """
    user_info = serializers.SerializerMethodField()
    token_info = serializers.SerializerMethodField()

    class Meta:
        model = AppUser
        fields = (
            'id', 'user_account', 'create_time', 'user_info', 'token_info',
        )

    def get_user_info(self, obj):
        try:
            script = UserInfo.objects.get(user_id=obj.id)
            return UserInfoSerializer(script).data
        except:
            return None

    def get_token_info(self, obj):
        try:
            script = Token.objects.get(user_id=obj.id)
            return TokenSerializer(script).data
        except:
            return None


class UserCardInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo
        fields = ('is_certification', 'idcard_no', 'idcard_img_bg', 'idcard_img_fg')


class UserInfoSerializer(serializers.ModelSerializer):
    user_medal = serializers.SerializerMethodField()
    user_account = serializers.SerializerMethodField()
    current_weight = serializers.SerializerMethodField()
    thumb_number = serializers.SerializerMethodField()

    class Meta:
        model = UserInfo
        fields = (
            'id',
            'weight',
            'height',
            'nick_name',
            'sex',
            'city',
            'age',
            'user_id',
            'portrait',
            'birth_year', 'birth_month', 'is_notify', 'balance', 'total_sport_time', 'continuity_sign', 'exp',
            'target_weight',
            'current_weight',
            'create_time',
            'medals',
            'user_medal',
            'thumb_number',
            'continuity_sign',
            'total_week_sport_time',
            'user_account',
            'bluetooth_key',
            'total_day_sport_time',
            'is_vip',
            'is_certification',
            'sport_day',
        )
        # fields = '__all__'

    def get_user_medal(self, obj):
        try:
            _medal = obj.medals
            script = UserMedal.objects.filter(pk__in=_medal.split(','))
            return UserMedalSerializer(script, many=True).data
        except:
            return None

    def get_current_weight(self, obj):
        try:
            script = AffairsRecord.objects.filter(user_id=obj.id).order_by('create_time').last()
            return script.present_weight
        except:
            return None

    def get_thumb_number(self, obj):
        try:
            script = AffairsRecord.objects.filter(user_id=obj.id, is_delete=False).aggregate(
                Sum('thumbs_num'))
            if script['thumbs_num__sum'] is None:
                return 0
            else:
                return script['thumbs_num__sum']
        except:
            return 0

    def get_user_account(self, obj):
        try:
            script = AppUser.objects.get(pk=obj.user_id)
            return script.user_account
        except:
            return None


class UserMedalSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserMedal
        fields = (
            'id',
            'medal_name',
            'medal_pic',
        )


class MachineSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo
        fields = (
            'id', 'uuid', 'name',
        )


class ConnectionRecordSerializer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()

    class Meta:
        model = ConnectionRecord
        fields = (
            'id', 'user_id', 'start_time', 'end_time', 'duration', 'avg_heart_rate',
            'max_heart_rate', 'min_heart_rate', 'user_info',
        )

    def get_user_info(self, obj):
        script = UserInfo.objects.get(pk=obj.user_id)
        return UserInfoSerializer(script).data


class HistoryConnectionRecordSerializer(serializers.ModelSerializer):
    class Meta:
        model = ConnectionRecord
        fields = (
            'id', 'user_id', 'start_time', 'end_time', 'duration', 'avg_heart_rate',
            'max_heart_rate', 'min_heart_rate',
        )


class HealthEverydaySerializer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()

    class Meta:
        model = UserInfo
        fields = (
            'id', 'user_id', 'weight', 'target_weight', 'waist', 'photo', 'user_info',
        )

    def get_user_info(self, obj):
        script = UserInfo.objects.get(pk=obj.user_id)
        return UserInfoSerializer(script).data


class AppEvaluateRecordSerializer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()

    class Meta:
        model = AppEvaluateRecord
        fields = (
            'id', 'user_id', 'evaluate_time', 'point', 'text', 'user_info',
        )

    def get_user_info(self, obj):
        script = UserInfo.objects.get(pk=obj.user_id)
        return UserInfoSerializer(script).data


class FollowRecordSerializer(serializers.ModelSerializer):
    following = serializers.SerializerMethodField()
    followed = serializers.SerializerMethodField()

    class Meta:
        model = FollowRecord
        fields = (
            'id', 'following_user_id', 'followed_user_id', 'following', 'followed',
        )

    def get_following(self, obj):
        script = UserInfo.objects.get(pk=obj.following_user_id)
        return UserInfoSerializer(script).data

    def get_followed(self, obj):
        script = UserInfo.objects.get(pk=obj.followed_user_id)
        return UserInfoSerializer(script).data


class JoinTrainRecordSerializer(serializers.ModelSerializer):
    train_info = serializers.SerializerMethodField()

    class Meta:
        model = JoinTrainRecord
        fields = (
            'id', 'user_id', 'train_id', 'train_info',
        )

    def get_train_info(self, obj):
        try:
            script = Training.objects.get(pk=obj.train_id)
            return TrainingSerializer(script).data
        except:
            return None


class AffairsRecordSerializer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()
    thumb_num = serializers.SerializerMethodField()
    comment_num = serializers.SerializerMethodField()

    class Meta:
        model = AffairsRecord
        fields = (
            'id', 'user_id', 'create_time', 'affair_text', 'affair_photo', 'browse_num', 'begin_weight',
            'present_weight', 'target_weight', 'user_info', 'thumb_num', 'comment_num', 'is_thumb', 'base_thumbs_num',
            'longitude', 'latitude'
        )

    def get_user_info(self, obj):
        script = UserInfo.objects.get(pk=obj.user_id)
        return UserInfoSerializer(script).data

    def get_thumb_num(self, obj):
        script = ThumbRecord.objects.filter(affair_id=obj.id)
        return len(script)

    def get_comment_num(self, obj):
        try:
            script = CommentRecord.objects.filter(affair_id=obj.id, level=1)
            return len(script)
        except:
            return 0


class ThumbRecordSerializer(serializers.ModelSerializer):
    class Meta:
        model = ThumbRecord
        fields = (
            'id', 'affair', 'operation_time', 'user',
        )


class CommentFirstRecordSerializer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()

    father_info = serializers.SerializerMethodField()

    class Meta:
        model = CommentRecord
        fields = (
            'id', 'affair', 'comment_text', 'operation_time', 'father_id', 'level', 'user_id', 'user_info',
            'father_info', 'top'
        )

    def get_user_info(self, obj):
        try:
            script = UserInfo.objects.get(pk=obj.user_id)
            return UserInfoSerializer(script).data
        except:
            return None

    def get_father_info(self, obj):
        try:
            script = CommentRecord.objects.get(pk=obj.father_id)
            return CommentFirstRecordSerializer(script).data
        except:
            return None


class CommentRecordSerializer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()
    son_info = serializers.SerializerMethodField()

    father_name = serializers.SerializerMethodField()

    father_info = serializers.SerializerMethodField()

    class Meta:
        model = CommentRecord
        fields = (
            'id', 'affair', 'comment_text', 'operation_time', 'father_id', 'level', 'user_id', 'user_info',
            'son_info', 'father_name', 'top', 'father_info',
        )

    def get_user_info(self, obj):
        try:
            script = UserInfo.objects.get(pk=obj.user_id)
            return UserInfoSerializer(script).data
        except:
            return None

    def get_son_info(self, obj):
        try:
            script = CommentRecord.objects.filter(top=obj.id)
            return CommentRecordSerializer(script, many=True).data
        except:
            return None

    def get_father_name(self, obj):
        try:
            script = CommentRecord.objects.get(pk=obj.father_id)
            return script.user.nick_name
        except:
            return None

    #
    def get_father_info(self, obj):
        try:
            script = CommentRecord.objects.get(pk=obj.father_id)
            return CommentFirstRecordSerializer(script).data
        except:
            return None


class TrainCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = TrainCategory
        fields = (
            'id', 'name', 'father_id',
        )


class TrainingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Training
        fields = (
            'id', 'background_image', 'browse_num', 'join_num', 'introduce', 'name', 'train_video', 'create_time',
            'cover_image', 'is_recommend', 'is_warm_up', 'base_browse_num', 'is_top'
        )


class UserSignSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserSign
        fields = (
            'id', 'user', 'sign_date', 'experience',
        )


class InformationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Information
        fields = (
            'id', 'background_image', 'info_text', 'cover_image', 'create_time', 'info_title', 'read_number', 'url',
            'type', 'order', 'is_top'
        )


class TokenSerializer(serializers.ModelSerializer):
    class Meta:
        model = Token
        fields = (
            'id', 'user', 'token',
        )


class ConnectionUserInfoSerializer(serializers.ModelSerializer):
    connect_type = serializers.SerializerMethodField()

    class Meta:
        model = UserInfo
        fields = (
            'id',
            'weight',
            'height',
            'nick_name',
            'sex',
            'city',
            'age',
            'portrait',
            'birth_year', 'birth_month', 'is_notify', 'balance', 'total_sport_time', 'total_week_sport_time',
            'continuity_sign', 'exp',
            'create_time',
            'target_weight',
            'connect_type',
            'medals',
        )

    def get_connect_type(self, obj):
        _today = datetime.date.today()
        _lastMonday = _today
        _nextSunday = _today
        while _lastMonday.weekday() != calendar.MONDAY:
            _lastMonday = _lastMonday - datetime.timedelta(days=1)
        while _nextSunday.weekday() != calendar.SUNDAY:
            _nextSunday = _nextSunday + datetime.timedelta(days=1)
        try:
            type1 = ConnectionTypeRecord.objects.filter(duration__isnull=False, user_id=obj.id, type=1,
                                                        start_time__gte=_lastMonday, end_time__lte=_nextSunday,
                                                        duration__lt=18000).values(
                'duration').annotate(result=Sum('duration'))
            _duration = 0
            for _type in type1:
                _duration += _type['duration']
            _hour1 = _duration / 3600
            _time1 = round(_hour1, 1)
        except:
            type1 = 0
            _time1 = "0.0"
        try:
            type2 = ConnectionTypeRecord.objects.filter(duration__isnull=False, user_id=obj.id, type=2,
                                                        start_time__gte=_lastMonday, end_time__lte=_nextSunday,
                                                        duration__lt=18000).values(
                'duration').annotate(result=Sum('duration'))
            _duration = 0
            for _type in type2:
                _duration += _type['duration']
            _hour2 = _duration / 3600
            _time2 = round(_hour2, 1)
        except:
            type2 = 0
            _time2 = "0.0"
        try:
            type3 = ConnectionTypeRecord.objects.filter(duration__isnull=False, user_id=obj.id, type=3,
                                                        start_time__gte=_lastMonday, end_time__lte=_nextSunday,
                                                        duration__lt=18000).values(
                'duration').annotate(result=Sum('duration'))
            _duration = 0
            for _type in type3:
                _duration += _type['duration']
            _hour3 = _duration / 3600
            _time3 = round(_hour3, 1)
        except:
            type3 = 0
            _time3 = "0.0"
        return_dict = {"reduce": _time1, "compact": _time2, "physiotherapy": _time3}
        return return_dict


class ConnectionTotalUserInfoSerializer(serializers.ModelSerializer):
    connect_type = serializers.SerializerMethodField()

    class Meta:
        model = UserInfo
        fields = (
            'id',
            'weight',
            'height',
            'nick_name',
            'sex',
            'city',
            'age',
            'portrait',
            'birth_year', 'birth_month', 'is_notify', 'balance', 'total_sport_time', 'total_week_sport_time',
            'continuity_sign', 'exp',
            'create_time',
            'target_weight',
            'connect_type',
            'medals',
        )

    def get_connect_type(self, obj):
        try:
            type1 = ConnectionTypeRecord.objects.filter(duration__isnull=False, user_id=obj.id, type=1,
                                                        duration__lt=18000
                                                        ).values(
                'duration').annotate(result=Sum('duration'))
            _duration = 0
            for _type in type1:
                _duration += _type['duration']
            _hour1 = _duration / 3600
            _time1 = round(_hour1, 1)
        except:
            type1 = 0
            _time1 = "0.0"
        try:
            _duration = 0
            type2 = ConnectionTypeRecord.objects.filter(duration__isnull=False, user_id=obj.id, type=2,
                                                        duration__lt=18000).values(
                'duration').annotate(Sum('duration'))
            for _type in type2:
                _duration += _type['duration']
            _hour2 = _duration / 3600
            _time2 = round(_hour2, 1)
        except:
            type2 = 0
            _time2 = "0.0"
        try:
            type3 = ConnectionTypeRecord.objects.filter(duration__isnull=False, user_id=obj.id, type=3,
                                                        duration__lt=18000
                                                        ).values(
                'duration').annotate(result=Sum('duration'))
            _duration = 0
            for _type in type3:
                _duration += _type['duration']
            _hour3 = _duration / 3600
            _time3 = round(_hour3, 1)
        except:
            type3 = 0
            _time3 = "0.0"
        return_dict = {"reduce": _time1, "compact": _time2, "physiotherapy": _time3}
        return return_dict


class BodyDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = BodyData
        fields = (
            'id', 'user', 'start_time', 'bmi',
            'fat_percentage', 'water_weight', 'visceral_fat_percentage',
            'muscle_weight',
            'bmr', 'bone_weight', 'fat_level', 'lbm', 'body_age', 'fat_control', 'fatty_liver_risk', 'm_smm',
            'muscle_control', 'physique',
            'score', 'standard_fat_percentage', 'water_percentage', 'weight_control', 'bone_muscle_weight',
            'protein_weight', 'sw', 'weight',
            'bmi_max', 'bmi_min', 'bone_muscle_weight_max', 'bone_muscle_weight_min', 'bone_weight_max',
            'bone_weight_min', 'fat_percentage_max',
            'fat_percentage_min', 'fat_weight_max', 'fat_weight_min', 'muscle_weight_max', 'muscle_weight_min',
            'protein_weight_max', 'protein_weight_min',
            'sw_max', 'sw_min', 'visceral_fat_percentage_max', 'visceral_fat_percentage_min', 'water_weight_max',
            'water_weight_min', 'weight_max', 'weight_min', 'fat_weight'
        )


class GetBodyDataListSerializer(serializers.ModelSerializer):
    class Meta:
        model = BodyData
        fields = (
            'id', 'start_time', 'fat_percentage_min', 'fat_percentage_max',
            'fat_percentage', 'weight',
        )


class BodyDataListSerializer(serializers.ModelSerializer):
    class Meta:
        model = BodyData
        fields = ('num'
                  )


class AppVersionSerializer(serializers.ModelSerializer):
    class Meta:
        model = AppVersionModel
        fields = (
            'version', 'create_time', 'allow_third_login', 'during_apple_verification', 'has_new_verion', 'must_update',
            'download_url')


class CommonProblemTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = CommonProblemTypeModel
        fields = ('name', 'sort_no', 'create_time')


class CommonProblemSerializer(serializers.ModelSerializer):
    type_name = serializers.SerializerMethodField()

    def get_type_name(self, obj):
        return obj.type.name

    class Meta:
        model = CommonProblemModel
        fields = ('title', 'create_time', 'sort_no', 'type', 'type_name', 'id')


class CommonProblemConnectSerializer(serializers.ModelSerializer):
    type_name = serializers.SerializerMethodField()

    def get_type_name(self, obj):
        return obj.type.name

    class Meta:
        model = CommonProblemModel
        fields = ('title', 'content', 'create_time', 'sort_no', 'type', 'type_name',)


class SuggestionRecordSerialiezer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()

    def get_user_info(self, obj):
        return UserInfoSerializer(obj.user).data

    class Meta:
        model = SuggestionRecordModel
        fields = ('create_time', 'content', 'user', 'user_info')


class BanNameSerializer(serializers.ModelSerializer):
    class Meta:
        model = BanNameModel
        fields = ('id', 'name')


class ApkVersionSerializer(serializers.ModelSerializer):
    class Meta:
        model = ApkVersionModel
        fields = ('id', 'create_time', 'version_no', 'version_description', 'is_delete')


class HardwareVersionSerializer(serializers.ModelSerializer):
    class Meta:
        model = HardwareVersionModel
        fields = ('id', 'create_time', 'category', 'manufacture', 'hw_version', 'fw_version')


class UserBodyDimensionSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserBodyDimension
        fields = (
            'id', 'body_weight', 'upper_bust', 'lower_bust', 'waist_circumference', 'hip_circumference', 'left_thigh',
            'right_thigh', 'left_arm', 'right_arm', 'user','create_time')
        ordering = ('-create_time',)

class AdminUserBodyDimensionSerializer(serializers.ModelSerializer):
    user_info = serializers.SerializerMethodField()

    def get_user_info(self, obj):
        return UserInfoSerializer(obj.user).data

    class Meta:
        model = UserBodyDimension
        fields = (
            'id', 'body_weight', 'upper_bust', 'lower_bust', 'waist_circumference', 'hip_circumference', 'left_thigh',
            'right_thigh', 'left_arm', 'right_arm', 'user','create_time','user_info')
        ordering = ('-create_time',)